#include<muduo/net/TcpClient.h>
#include<muduo/net/EventLoop.h>
#include<muduo/net/TcpConnection.h>
#include<muduo/net/Buffer.h>
#include<muduo/base/CountDownLatch.h>
#include<muduo/net/EventLoopThread.h>
#include<iostream>
#include<string>


class DictClient
{

public:
    DictClient(const std::string &sip ,int port)
        :_loopthread()//一旦实例化好了,内部自动实现循环监控
        ,_baseloop( _loopthread.startLoop())
        ,_client(_baseloop ,muduo::net::InetAddress(sip ,port) ,"DictClient")
        ,_downlatch(1) //初始化计数器为1
    {
        //用bind解决多一个this指针问题
        //设置回调函数
        _client.setConnectionCallback(std::bind(&DictClient::onConnection,this ,std::placeholders::_1));
        _client.setMessageCallback(std::bind(&DictClient::onMessage,this ,
            std::placeholders::_1 ,std::placeholders::_2 ,std::placeholders::_3));

        //连接服务器
        _client.connect(); //非阻塞接口,connect进行完,链接不一定建立好了,要用countdownlatch限制
        _downlatch.wait();//进入阻塞状态


    }
    bool Send(std::string msg)
    {
        if(_conn->connected() == false)
        {
            std::cout<<"链接已断开 ,发送数据失败 \n";
            return false;
        }
        _conn->send(msg);
        return true;
    }
private:
    void onConnection(const muduo::net::TcpConnectionPtr& conn)//链接建立时/断开时的回调方法
    {
        if(conn->connected())
        {
            std::cout<<"链接建立\n";
            _downlatch.countDown();//计数-- ,为零时结束阻塞
            _conn=conn;
        }
        else
        {
            std::cout<<"链接断开\n";
            _conn.reset();
        }
    }

    //收到消息的处理函数
    void onMessage(const muduo::net::TcpConnectionPtr &conn ,muduo::net::Buffer *buff ,muduo::Timestamp)
    {
        //想要接受到数据,首先要触发可读事件;想要触发可读事件,就要先开始事件循环监控
        std::string res = buff->retrieveAllAsString();
        std::cout<< res <<std::endl;
    }

private:
    muduo::net::EventLoopThread _loopthread;//封装好的eventloopthread ,里面有loop和thread 
    muduo::net::TcpConnectionPtr _conn; //用来发信息
    muduo::CountDownLatch _downlatch;
    muduo::net::EventLoop* _baseloop;
    muduo::net::TcpClient _client;//EventLoop* loop,  const InetAddress& serverAddr  ,  const string& nameArg
};


int main()
{
    DictClient client("127.0.0.1" ,9090);
    while(1)
    {
        std::string msg;
        std::cin>>msg;
        client.Send(msg);
    }

    return 0;
}